﻿using Cinemachine;
using LogSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Playables;
using Yoozoo.Framework.Core;
using Yoozoo.Gameplay.Liberty;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.Mars.Got;

namespace Yoozoo.Core.Timeline
{
    public class TimelineConstructorMgr : SingletonMono<TimelineConstructorMgr>
    {
        private LinkedList<TimelineConstructor> _timelineConstructors;

        private LinkedListNode<TimelineConstructor> _currentNode;

        private Dictionary<string, Action<TimelineConstructor>> _actionMap;

        private HashSet<string> _loadingTimelines;

        private int _characterId = 0;

        private readonly System.Diagnostics.Stopwatch _stopwatch = 
            new System.Diagnostics.Stopwatch();
        
        private void Update()
        {
            if (_currentNode!=null)
            {
                if (!_currentNode.Value.buildComplete)
                {
                    _stopwatch.Reset();
                    _stopwatch.Start();
                    while (!_currentNode.Value.buildComplete && _stopwatch.ElapsedMilliseconds < 10)
                    {
                        _currentNode.Value.OnUpdate();
                    }
                    _stopwatch.Stop();
                }
                else
                {
                    if (_actionMap!=null)
                    {
                        _actionMap.TryGetValue(_currentNode.Value.tLineName, out var action);
                        if (action!=null)
                        {
                            action?.Invoke(_currentNode.Value);
                            _actionMap.Remove(_currentNode.Value.tLineName);
                        }
                    }
                    
                    _currentNode = _currentNode.Next;
                }
            }
        }

        public void GetTimelineConstructor(string tLineName, Action<TimelineConstructor> cAction, string path, string cameraType, float planeDistance,ETimelinePathType pathType = ETimelinePathType.City)
        {
            bool t = false;
            if (_timelineConstructors!=null)
            {
                foreach (var timelineConstructor in _timelineConstructors)
                {
                    if (timelineConstructor.tLineName == tLineName)
                    {
                        if (timelineConstructor.buildComplete)
                        {
                            cAction?.Invoke(timelineConstructor);
                        }
                        else
                        {
                            if (_actionMap==null)
                            {
                                _actionMap = new Dictionary<string, Action<TimelineConstructor>>();
                            }

                            if (!_actionMap.ContainsKey(tLineName))
                            {
                                _actionMap[tLineName] = cAction;
                            }
                            else
                            {
                                _actionMap[tLineName] += cAction;
                            }
                        }
                        t = true;
                        break;
                    }
                }
            }

            if (!t)
            {
                // 没有就走异步加载创建
                if (_actionMap==null)
                {
                    _actionMap = new Dictionary<string, Action<TimelineConstructor>>();
                }

                if (!_actionMap.ContainsKey(tLineName))
                {
                    _actionMap[tLineName] = cAction;
                }
                else
                {
                    _actionMap[tLineName] += cAction;
                }

                string tLinePath;
                if (pathType == ETimelinePathType.City)
                {
                    tLinePath = $"Assets/ResourcesAssets/City/Timelines/{tLineName}.prefab";
                }
                else
                {
                    tLinePath = $"Assets/ResourcesAssets/Pve/Survivor/Prefabs/Timeline/{tLineName}.prefab";
                }
                if (!string.IsNullOrEmpty(path))
                {
                    tLinePath = $"{path}/{tLineName}.prefab";
                }

                if (_loadingTimelines!=null && _loadingTimelines.Contains(tLinePath))
                {
                    // 正在加载中
                    return;
                }
                
                if (_loadingTimelines == null) _loadingTimelines = new HashSet<string>();
                _loadingTimelines.Add(tLinePath);
                ResLoader resLoader = ResLoader.Alloc();
                resLoader.Add2Load(tLinePath, ((success, assetName, asset) =>
                {
                    //_loadingTimelines.Remove(tLinePath);
                    if (!success)
                    {
                        return;
                    }
                    GameObject o = GameObject.Instantiate(asset as GameObject);
                    TimelineConstructor timelineConstructor = o.GetComponent<TimelineConstructor>();

                    if (timelineConstructor == null)
                    {
#if UNITY_EDITOR
                        EditorUtility.DisplayDialog("Error", $"发生错误，Timeline没有挂载TimelineConstructor脚本：{assetName}", "OK");
#endif
                        Debug.LogError(LogModule.Guide,$"Timeline没有挂载TimelineConstructor脚本：{assetName}");     
                        return;
                    }
                    
                    //这里尽早处理一下横竖屏问题
                    /*TimelineScreenOrientationController screenOrientationController = o.GetComponent<TimelineScreenOrientationController>();
                    if (screenOrientationController != null)
                    {
                        screenOrientationController.OnInit();
                    }*/

                    timelineConstructor.tLineName = tLineName;
                    timelineConstructor.tLinePath = tLinePath;
                    timelineConstructor.resLoader = resLoader;
                    AddConstructor(timelineConstructor);
                    if (timelineConstructor.tHCamera)
                    {
                        timelineConstructor.audioListener = timelineConstructor.tHCamera.GetComponent<AudioListener>();
                        if (timelineConstructor.audioListener)
                        {
                            timelineConstructor.audioListener.enabled = false;
                        }
                    }

                    if (timelineConstructor.virtualCameras==null || timelineConstructor.virtualCameras.Count == 0)
                    {
                        timelineConstructor.virtualCameras = timelineConstructor.gameObject
                            .GetComponentsInChildren<CinemachineVirtualCamera>(true).ToList();
                        foreach (var virtualCamera in timelineConstructor.virtualCameras)
                        {
                            virtualCamera.enabled = false;
                        }
                    }
                    
                    if (!timelineConstructor.setCube)
                    {
                        timelineConstructor.setCube = GetComponentInChildren<SetCube>(true);
                    }
                    
                    o.transform.localScale = Vector3.zero;
                    o.transform.position = new Vector3(10000, 10000, 10000);

                    // 特殊处理一下相机需求
                    if (!string.IsNullOrEmpty(cameraType))
                    {
                        if (cameraType == "UICamera")
                        {
                            var canvas = o.transform.Find("Canvas").GetComponent<Canvas>();
                            if (canvas != null)
                            {
                                var uiCamera = GameObject.Find("UIRoot/UICamera").GetComponent<Camera>();
                                canvas.renderMode = RenderMode.ScreenSpaceCamera;
                                canvas.worldCamera = uiCamera;
                                if (planeDistance > 0) canvas.planeDistance = planeDistance;
                            }
                        }
                    }
                }));
                resLoader.Load();
                //Debug.LogError(LogModule.Guide,$"还没有构建Timeline，请提前构建：{tLineName}");
            }
        }

        // 预构建Timeline，会将Timeline实例化
        public void AddTimelineInstance(string tLinePath,Action<TimelineConstructor> callback)
        {
            if (_loadingTimelines!=null && _loadingTimelines.Contains(tLinePath))
            {
                // 正在加载中
                callback?.Invoke(null);
                return;
            }
            
            if (_loadingTimelines == null) _loadingTimelines = new HashSet<string>();
            _loadingTimelines.Add(tLinePath);
            ResLoader resLoader = ResLoader.Alloc();
            resLoader.Add2Load(tLinePath, ((success, assetName, asset) =>
            {
                //_loadingTimelines.Remove(tLinePath);
                if (!success)
                {
                    return;
                }
                GameObject o = GameObject.Instantiate(asset as GameObject);
                TimelineConstructor timelineConstructor = o.GetComponent<TimelineConstructor>();

                if (timelineConstructor == null)
                {
#if UNITY_EDITOR
                    EditorUtility.DisplayDialog("Error", $"发生错误，Timeline没有挂载TimelineConstructor脚本：{assetName}", "OK");
#endif
                    Debug.LogError(LogModule.Guide,$"Timeline没有挂载TimelineConstructor脚本：{assetName}");     
                    return;
                }

                timelineConstructor.tLinePath = tLinePath;
                timelineConstructor.resLoader = resLoader;
                timelineConstructor.playableDirector.timeUpdateMode = DirectorUpdateMode.Manual;
                timelineConstructor.playableDirector.Play();    // 预热
                Timers.inst.CallLater((o1 =>
                {
                    timelineConstructor.playableDirector.Pause();
                    timelineConstructor.pausing = true;
                }));
                AddConstructor(timelineConstructor);
                if (timelineConstructor.tHCamera)
                {
                    timelineConstructor.audioListener = timelineConstructor.tHCamera.GetComponent<AudioListener>();
                    if (timelineConstructor.audioListener)
                    {
                        timelineConstructor.audioListener.enabled = false;
                    }
                }
                
                if (timelineConstructor.virtualCameras==null || timelineConstructor.virtualCameras.Count == 0)
                {
                    timelineConstructor.virtualCameras = timelineConstructor.gameObject
                        .GetComponentsInChildren<CinemachineVirtualCamera>(true).ToList();
                    foreach (var virtualCamera in timelineConstructor.virtualCameras)
                    {
                        virtualCamera.enabled = false;
                    }
                }

                if (!timelineConstructor.setCube)
                {
                    timelineConstructor.setCube = GetComponentInChildren<SetCube>(true);
                }
                
                // 不使用SetActive(false),防止Animator Rebind
                o.transform.localScale = Vector3.zero;
                o.transform.position = new Vector3(10000, 10000, 10000);
                callback?.Invoke(timelineConstructor);
            }));
            resLoader.Load();
        }
        
        public void DestroyConstructor(TimelineConstructor constructor)
        {
            if (constructor && constructor.gameObject)
            {
                constructor.gameObject.transform.localScale = Vector3.zero;
                Timers.inst.CallLater((o =>
                {
                    GameObject.DestroyImmediate(constructor.gameObject);
                }));
            }
                   
            if (constructor.resLoader!=null)
            {
                constructor.resLoader.Recycle2Cache();
                constructor.resLoader = null;
            }
        }
        
        public void DestroyTimelineConstructor(string tLineName)
        {
            if (_timelineConstructors == null || _timelineConstructors.Count == 0)
            {
                return;
            }
            foreach (var timelineConstructor in _timelineConstructors)
            {
                if (timelineConstructor.tLineName == tLineName)
                {
                    RemoveConstructor(timelineConstructor);
                    if (timelineConstructor && timelineConstructor.gameObject)
                    {
                        timelineConstructor.gameObject.transform.localScale = Vector3.zero;
                        Timers.inst.CallLater((o =>
                        {
                            if (timelineConstructor && timelineConstructor.gameObject)
                            {
                                GameObject.DestroyImmediate(timelineConstructor.gameObject);
                            }
                        }));
                    }
                    Timers.inst.CallLater((o =>
                    {
                        if (timelineConstructor.resLoader!=null)
                        {
                            timelineConstructor.resLoader.Recycle2Cache();
                            timelineConstructor.resLoader = null;
                        }
                    }));
                    break;
                }
            }
        }

        public void ClearTimelines()
        {
            if (_timelineConstructors == null || _timelineConstructors.Count == 0)
            {
                return;
            }

            List<GameObject> destroyList = null;
            if (_timelineConstructors.Count > 0)
            {
                destroyList = new List<GameObject>();
            }
            foreach (var constructor in _timelineConstructors)
            {
                if (constructor)
                {
                    if (constructor.playableDirector && constructor.playableDirector.gameObject)
                    {
                        destroyList.Add(constructor.playableDirector.gameObject);
                    }
                
                    if (constructor.resLoader!=null)
                    {
                        constructor.resLoader.Recycle2Cache();
                        constructor.resLoader = null;
                    }
                }
            }

            if (destroyList != null)
            {
                for (int i = 0; i < destroyList.Count; i++)
                {
                    GameObject.DestroyImmediate(destroyList[i]);
                }
            }
            _timelineConstructors.Clear();
            _loadingTimelines?.Clear();
        }

        public void ResetTimelines()
        {
            ClearTimelines();
            _timelineConstructors?.Clear();
            _loadingTimelines?.Clear();
            _actionMap?.Clear();
        }

        public void AddConstructor(TimelineConstructor constructor)
        {
            if (_timelineConstructors == null)
            {
                _timelineConstructors = new LinkedList<TimelineConstructor>();
            }
            else
            {
                //判断是否有重复
                var tempNode = _currentNode;
                while (tempNode != null)
                {
                    if (tempNode.Value == constructor)
                    {
                        return;
                    }
                    tempNode = tempNode.Next;
                }
            }
           
            
            
            var node = new LinkedListNode<TimelineConstructor>(constructor);
            _timelineConstructors.AddLast(node);

            if (_currentNode == null)
            {
                _currentNode = node;
            }
        }

        public void RemoveConstructor(TimelineConstructor constructor)
        {
            if (_currentNode != null)
            {
                if (constructor == _currentNode.Value)
                {
                    _currentNode = _currentNode.Next;
                }
            }
            _timelineConstructors.Remove(constructor);
            var path = constructor.tLinePath;
            if (_loadingTimelines != null && _loadingTimelines.Contains(path))
            {
                _loadingTimelines.Remove(path);
            }
            constructor.OnRemoved();
        }

        public void SetTimelineCharacterId(int characterId)
        {
            _characterId = characterId;
        }

        public int GetTimelineCharacterId()
        {
            return _characterId;
        }

        public void RefreshTimelineCharacterId()
        {
            if (_timelineConstructors == null || _timelineConstructors.Count == 0)
            {
                return;
            }
            
            foreach (var constructor in _timelineConstructors)
            {
                if (constructor)
                {
                    var characterCtl = constructor.gameObject.GetComponent<PlayerCharacterController>();
                    if (characterCtl != null)
                    {
                        characterCtl.RefreshCharacter();
                    }
                }
            }
        }
        
    }
}
